#ifndef document_H
#define document_H

#include <QGraphicsView>
#include <QList>
#include <KUndoStack>

#include "page.h"
#include "tools/tool.h"

/**
 * A Document opened in the journal. Represents a tab in the main tab widget.
 */
class Document : public QGraphicsView
{
    Q_OBJECT

public:
    /**
     * Creates a new Document with the given parent (usually a JournalWindow).
     */
    Document(QWidget *parent=0);

    /**
     * The current scale level of the document.
     */
    qreal scale() const { return m_scale; }

    /**
     * Return the previous scaling level.
     */
    qreal prevScale() const { return m_scalePrevious; }

    /**
     * Return the file name of this document.
     */
    QString fileName() { return m_fileName; }

    /**
     * Set the file name of this document.
     * @param name The new name.
     */
    void setFileName(QString name) { m_fileName = name; emit fileNameChanged(name, this);}

    /**
     * Try to close this document.
     * Asks to save unsaved changes.
     * @return true when the document can be closed.
     */
    bool close();

    /**
     * Return a reference of this documents page list.
     */
    QList<Page*>* pageList() const { return m_pages;}

    /**
     * Return the Page that is currently in the center.
     */
    Page* currentPage();

    /**
     * Return the current tool.
     */
    Tool *currentTool() { return m_currentTool; }

protected:
    /**
     * Overrides the mouse press event to give it to the current tool.
     */
    void mousePressEvent(QMouseEvent *event);

    /**
     * Overrides the mouse move event to give it to the current tool.
     */
    void mouseMoveEvent(QMouseEvent *event);

    /**
     * Overrides the mouse release event to give it to the current tool.
     */
    void mouseReleaseEvent(QMouseEvent *event);

    /**
     * Overrides the double click event to give it to the current tool.
     */
    void mouseDoubleClickEvent(QMouseEvent *event);

    /**
     * Overrides the tablet event to give it to the current tool.
     */
    void tabletEvent(QTabletEvent *event);

private:
    /**
     * The file name of this document. Is used for saving and as the label for the document's tab.
     */
    QString m_fileName;

    /**
     * The current tool.
     */
    Tool *m_currentTool;

    /**
     * The list of pages this document has.
     */
    QList<Page*> *m_pages;

    /**
     * The current scaling factor of the document.
     */
    qreal m_scale;

    /**
     * The scaling that was used previously.
     */
    qreal m_scalePrevious;

    /**
     * The undo stack of commands that have been performed on this document.
     */
    KUndoStack *m_undoStack;

    /**
     * Whether the document has unsaved changes.
     */
    bool m_dirty;

    /**
     * Creates and configures the scene in which the pages are shown.
     */
    void configureScene();

    /**
     * Delete the current tool.
     */
    void unsetTool();

public slots:
    /**
     * Add a new page at the end of the document.
     * The page will have the same size and background as the one before it.
     */
    void addNewPage();

    /**
     * Add a new page at the given index.
     * The page will have the same size and background as the one before it.
     *
     * @param index The index which will be the one of the new page.
     **/
    void addNewPage(int index);

    /**
     * Add a new page after the given page.
     * The page will have the same size and background as the one before it.
     */
    void addNewPage(Page *page);

    /**
     * Insert a page at the given index.
     * @param index The index of the page.
     * @param page to insert.
     */
    void insertPage(int index, Page *page);

    /**
     * Insert a page after the given page.
     * @param indexPage The index of the page.
     * @param page to insert.
     */
    void insertPage(Page *indexPage, Page *page);

    /**
     * Returns a reference to the page that is at the given point.
     * Remember to check the result for null.
     *
     * @param point The QPointF in scene coordinates.
     * @return Pointer to the page at that location or 0 when none could be found.
     */
    Page* pageAt(const QPointF point);

    /**
     * Recalculate the scene-position for each page and place them correctly in the scene.
     */
    void rePositionPages();

    /**
     * Undo changes done to this document.
     */
    void undo();

    /**
     * Redo undone changes for this document.
     */
    void redo();

    /**
     * Push a QUndoCommand on the QUndoStack of this document.
     */
    void pushUndoCommand(QUndoCommand *cmd);

    /**
     * Set the current tool to the pen tool.
     */
    void setPenTool();

    /**
     * Set the current tool to the eraser tool.
     */
    void setEraserTool();

    /**
     * Remove the given page.
     */
    void removePage(Page* page);

    /**
     * Set the zoom level for this document.
     */
    void setScale(qreal level);

    /**
     * Move a Page up in the page-order.
     */
    void movePageUp(Page *page);

    /**
     * Move a page down in the page order.
     */
    void movePageDown(Page *page);

signals:
    /**
     * Emitted when the file name for this document has changed.
     * @param newName the new name of this document.
     * @param document The document that has its name changed.
     */
    void fileNameChanged(QString newName, Document *document);
};

#endif
